// Module for Karel dictionary

/// <reference path="../typings/jquery/jquery.d.ts" />
/// <reference path="../typings/jquery/jqueryui.d.ts" />

// import UI interfaces
import I = require("./Interfaces");

// import the dictionary module
import Dic = require("../MiddleLayer/Execution/Dictionary");

// import command module
import Cmd = require("../MiddleLayer/Execution/Commands");

// import execution engine module
import Exec = require("../MiddleLayer/Execution/ExecutionEngine");

// import message box
import MsgBox = require("./MessageBox");

// import dialogs
import Dlg = require("./Dialog");

// import localization
import Loc = require("./Localization");

declare function SelectSelectableElement(a: any, b: any);

// the presenter itself
export class KarelDictionary implements I.IDictionary {

    // reference to the dictionary
    private mDictionary: Dic.Dictionary;
    private mEngine: Exec.ExecutionEngine;
    private mLocalization: Loc.Localization;

    // dependencies
    private mCommandLine: I.ICommandLine;
    private mEditor: I.IEditor;

    // constructor
    public constructor() {
        // set vars
        this.mCommandLine = null;
        this.mEditor = null;

        // set reference
        this.mDictionary = Dic.Dictionary.Instance;
        this.mEngine = Exec.ExecutionEngine.Instance;
        this.mLocalization = Loc.Localization.Instance;

        // build control
        this.BuildControl();
        this.LayoutControl();

        // show commands
        this.RefreshCommands();
    }

    // sets the UI dependencies
    public SetDependencies(commandLine: I.ICommandLine, editor: I.IEditor) {
        this.mCommandLine = commandLine;
        this.mEditor = editor;
    }

    // builds the control
    private BuildControl(): void {
        var that = this;

        // init the bottom toolbar
        $("#idBottomDictionaryToolbar button").button();


        // initialize the command list
        $("#idCommandList").selectable({
            selected: function (event, ui) {
                // get the command name
                var item = ui.selected;
                var commandName = $(item).html();

                that.mEditor.ShowCommand(commandName);
            }
        });

        // attach command dictionary handlers

        // load dictionary command
        $("#idLoadDictionaryCommand").click(function () {

            // load dictionary anonymous function
            var loadDictionary = function () {
                Dlg.Dialog.Instance.ShowDictionaryUploadDialog(function (file) {

                    // read the file asynch
                    var reader = new FileReader();
                    reader.onload = function (e) {
                        var sourceCode = reader.result;

                        // clear the dictionary before input
                        that.mDictionary.ClearDictionary();

                        // invoke import to the dictionary
                        that.mDictionary.ImportDictionary(sourceCode);

                        // refresh the command list
                        that.RefreshCommands();

                    }
                    reader.onerror = function (e) {
                        MsgBox.MessageBox.Instance.ShowModal("DictionaryCorrupted", "Error");
                    }
                    reader.readAsText(file);  
                });
            }
                        
            // check if user wants the delete the dictionary before importing
            if (that.mDictionary.IsDictionaryEmpty() == false) {
                MsgBox.MessageBox.Instance.Confirm("DeleteDictionary", "DeleteDictionaryTitle", function (result) {
                    // if deleting confirmed
                    if (result == MsgBox.eConfirmResult.Yes) {
                        // if confirmed, continue with importing
                        loadDictionary();
                    } else {
                        return;
                    }
                });

                return;
            }

            // invoke load dictionary function
            loadDictionary();
        });

        // save dictionary command
        $("#idSaveDictionaryCommand").click(function () {
            // check dictionary not empty
            if (that.mDictionary.IsDictionaryEmpty() == true) {
                MsgBox.MessageBox.Instance.ShowModal("DictionaryEmpty", "Notification");
                return;
            }

            // get the complete source code of all commands
            var sourceCode = that.mDictionary.ExportDictionary();

            // POST it to the server
            $.post("/Pages/Upload.aspx",
                {
                    "Content": sourceCode
                }, function (data, textStatus, jqXHR) {
                    // run the download dialog
                    Dlg.Dialog.Instance.ShowDictionaryDownloadDialog();                                       

                }).fail(function () {
                    MsgBox.MessageBox.Instance.ShowModal("InternetError", "Error");
                });                  
        });

        // clear dictionary command
        $("#idClearDictionaryCommand").click(function () {
            // if dictionary not empty
            if (that.mDictionary.IsDictionaryEmpty() == false) {
                MsgBox.MessageBox.Instance.Confirm("DeleteDictionary", "DeleteDictionaryTitle", function (result) {
                    // if deleting confirmed
                    if (result == MsgBox.eConfirmResult.Yes) {

                        that.mDictionary.ClearDictionary();
                        that.RefreshCommands();

                        // save the commands to the localStorage
                        that.mDictionary.Save();
                    }
                });
            }
        });

        // Invokes the help manual
        $("#idHelpCommand").click(function () {
            Dlg.Dialog.Instance.ShowHelp();
        });       

        // Invokes the author info modal dialog
        $("#idAuthorsCommand").click(function () {
            Dlg.Dialog.Instance.ShowAuthors();
        });
    }

    public LayoutControl(): void {
        // layout the editor
        var height = $("#idDictionaryContainer").innerHeight() - $("#idBottomDictionaryToolbar").outerHeight();
        $("#idDictionary").outerHeight(height);
    }

    // refreshes the commands
    public RefreshCommands(commandToSelect: string = null): void  {
        // get the command list
        var commands = this.mDictionary.GetListOfCommands();

        // prepare the HTML content
        var htmlContent = "";
        for (var i = 0; i < commands.length; i++) {
            // get the command
            var cmd = commands[i];

            // prepare the item HTML
            var htmlItem = "<li class=\"ui-widget\" >";
            htmlItem += cmd.toLocaleUpperCase();
            htmlItem += "</li>";

            // add to the global HTML
            htmlContent += htmlItem;
        }

        // set the HTML content
        $("#idCommandList").html(htmlContent);

        // get the maximum item width
        var maxWidth = 0;
        $("#idCommandList li").each(function (index, elem) {
            maxWidth = Math.max($(elem).width(), maxWidth);
        });

        // set the maximum item width
        $("#idCommandList li").width(maxWidth);

        // add right-click activation
        $("#idCommandList li").on("contextmenu", function (event) {
            SelectSelectableElement($("#idCommandList"), $(event.target));
        });

        var that = this;

        // localize menu
        var runCmd = this.mLocalization.Get("RunCmd");
        var editCmd = this.mLocalization.Get("EditCmd");
        var delCmd = this.mLocalization.Get("DelCmd");

        // add context menu to the selectable items
        (<any>$("#idCommandList li")).contextmenu({
            menu: [
                { title: runCmd, cmd: "run" },
                { title: editCmd, cmd: "edit" },
                { title: delCmd, cmd: "delete" },
            ],
            select: function (event, ui) {
                if (ui.cmd == "run") {
                    that.mCommandLine.RunCommand(ui.target.text());
                }
                else if (ui.cmd == "edit") {
                    that.mEditor.EditCommand(ui.target.text());
                }
                else if (ui.cmd == "delete") {
                    MsgBox.MessageBox.Instance.Confirm("DeleteCommand", "DelCmdTitle", function (result) {
                        // if the user has confirmed the delete operation
                        if (result == MsgBox.eConfirmResult.Yes) {
                            if (that.mDictionary.DeleteCommand(ui.target.text()) == false) {
                                // display the error
                                MsgBox.MessageBox.Instance.ShowModal("ErrorDelete", "Error");
                            }
                            else {
                                // if delete successful
                                that.RefreshCommands();

                                // save the commands to the localStorage
                                that.mDictionary.Save();
                            }
                        }
                    });
                }
            },
            beforeOpen: function (event, ui) {
                (<any>$(this)).contextmenu("enableEntry", "run", that.mEngine.IsRunning == false);
                (<any>$(this)).contextmenu("enableEntry", "edit",
                    that.mDictionary.IsSystemCommand(ui.target.text()) == false && that.mEditor.IsEditMode() == false);               
                (<any>$(this)).contextmenu("enableEntry", "delete", that.mDictionary.IsSystemCommand(ui.target.text()) == false);               
                return true;
            }
        });

        // reset the shown command
        if (this.mEditor != null) {
            // if no command to be shown
            if (commandToSelect == null) {
                this.mEditor.ShowCommand(null);
            }
            else {
                // iterate all commands
                $("#idCommandList li").each(function (idx, elem) {
                    // if command to select found
                    if ($(this).text().toLocaleUpperCase() == commandToSelect.toLocaleUpperCase()) {
                        // invoke the selection process
                        SelectSelectableElement($("#idCommandList"), $(this));
                    }
                });
            }
        }
    }
}
